package ru.agiledev.aos.core;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import ru.agiledev.aos.commons.dto.SearchEntry;
import ru.agiledev.aos.commons.dto.SemanticQuery;
import ru.agiledev.aos.core.util.Transformer;
import ru.agiledev.aos.analyzer.SemanticAnalyzer;
import ru.agiledev.aos.data.HibernateUtil;
import ru.agiledev.aos.data.domain.SearchResultDump;
import ru.agiledev.ysearch.YSearch;

import java.io.IOException;
import java.util.List;

/**
 * Created by Anton Kirillov
 * Date: 8/12/11
 */
public class SemanticEngine {

    //top-level method for search
    private List<SearchEntry> search(String query, int page){
        List<SearchEntry> results = null;

        String xmlResults = getDump(query);

        if(xmlResults!=null){
            results = Transformer.transform(xmlResults);
        }else {

            YSearch searcher = new YSearch("a-kirillov-a-search-in", "03.75627595:9689e3ecc186de751d138bc36a5a0069");

            try {
                xmlResults = searcher.getSearchResults(query);
            } catch (IOException e) {
                e.printStackTrace();
            }

            if(xmlResults!=null){
                results = Transformer.transform(xmlResults);
            }

            if(results.size()>0){
                writeDump(query, xmlResults);
            }
        }

        return results;
    }

    /**
     * Method for searching results based on transformed query
     * @param query transformed query
     * @return list of entries
     */
    public List<SearchEntry> search(SemanticQuery query){
        if((query.getQueries()==null)||(query.getQueries().size()==0)){
            return search(query.getInitialQuery(), 0);
        } else {
            QueriesRunner runner = new QueriesRunner(query);
            List<SearchEntry> entries = runner.runQueries();

            List<SearchEntry> res = null;

            if(entries.size()>0){
                ResultsRanker ranker = new ResultsRanker();
                res = ranker.rankQueries(query.getFirstObject(), entries);
            }

            return res;
        }
    }

    //method for transformation String NL-query to semantically extended
    public SemanticQuery transformQuery(String query){
        SemanticAnalyzer analyzer = new SemanticAnalyzer();
        return analyzer.transformQuery(query);
    }


    private String getDump(String query){
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        Criteria criteria = session.createCriteria(SearchResultDump.class).add(Restrictions.eq("query", query));

        List<SearchResultDump> xml = criteria.list();
        if(xml.size() == 0){
            session.close();
            return null;
        } else {
            if(xml.get(0).getXml().length()>0){
                session.close();
                return xml.get(0).getXml();
            } else{
                session.close();
                return null;
            }
        }
    }


    private void writeDump(String query, String xml){
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();

        SearchResultDump dump = new SearchResultDump(query, xml);

        session.save(dump);
        session.getTransaction().commit();
        session.close();
    }
}
